﻿using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using FileTransferSystem.Models;
using FileTransferSystem.Services;

namespace FileTransferSystem.Services
{
    /// <summary>
    /// 文件传输类，处理具体的文件传输逻辑
    /// </summary>
    public class FileTransfer
    {
        private readonly HistoryManager _historyManager;
        private readonly string _tempFolderPath;
        private FileTransferInfo _transferInfo;
        private CancellationTokenSource _cancellationTokenSource;
        private System.Timers.Timer _progressTimer;
        private TcpListener _listener;
        private TcpClient _client;
        private NetworkStream _networkStream;
        private FileStream _fileStream;
        private bool _isTransferring;
        private bool _isReceivingFileInfo;
        private MemoryStream _preReadData;

        /// <summary>
        /// 传输取消事件
        /// </summary>
        public event EventHandler<FileTransferInfo> TransferCanceled;

        /// <summary>
        /// 传输完成事件
        /// </summary>
        public event EventHandler<FileTransferInfo> TransferCompleted;

        public FileTransfer(FileTransferInfo transferInfo, HistoryManager historyManager, string tempFolderPath)
        {
            _transferInfo = transferInfo;
            _historyManager = historyManager;
            _tempFolderPath = tempFolderPath;
            _cancellationTokenSource = new CancellationTokenSource();
            _preReadData = new MemoryStream();
        }

        /// <summary>
        /// 开始发送文件
        /// </summary>
        public async Task StartSending(bool isResume)
        {
            try
            {
                _isTransferring = true;

                // 保存传输状态
                SaveTransferState();

                // 连接到接收端
                await ConnectToReceiver();

                // 发送文件信息
                await SendFileInfo();

                // 启动进度显示
                StartProgressDisplay();

                // 发送文件数据
                await SendFileData();

                // 传输完成
                _isTransferring = false;
                TransferCompleted?.Invoke(this, _transferInfo);

                // 清理临时文件
                CleanupTempFiles();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"发送失败: {ex.Message}");
                _isTransferring = false;
                TransferCanceled?.Invoke(this, _transferInfo);
            }
            finally
            {
                StopProgressDisplay();
                CloseConnections();
            }
        }

        /// <summary>
        /// 开始接收文件
        /// </summary>
        public async Task StartReceiving(bool isResume)
        {
            try
            {
                _isTransferring = true;
                _isReceivingFileInfo = true;

                // 保存传输状态
                SaveTransferState();

                // 启动监听
                StartListening();

                Console.WriteLine("等待发送端连接... (输入0取消等待)");

                // 等待发送端连接，支持取消
                var waitTask = WaitForSender();
                var cancelTask = WaitForCancelInput();

                var completedTask = await Task.WhenAny(waitTask, cancelTask);

                if (completedTask == cancelTask && await cancelTask)
                {
                    Console.WriteLine("等待已取消");
                    _isTransferring = false;
                    TransferCanceled?.Invoke(this, _transferInfo);
                    return;
                }

                // 处理可能的测试连接消息
                await HandlePossibleTestConnection();

                // 接收文件信息
                await ReceiveFileInfo();

                _isReceivingFileInfo = false;

                // 启动进度显示
                StartProgressDisplay();

                // 接收文件数据
                await ReceiveFileData(isResume);

                // 传输完成
                _isTransferring = false;
                TransferCompleted?.Invoke(this, _transferInfo);

                // 清理临时文件
                CleanupTempFiles();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"接收失败: {ex.Message}");
                _isTransferring = false;
                TransferCanceled?.Invoke(this, _transferInfo);
            }
            finally
            {
                StopProgressDisplay();
                CloseConnections();
            }
        }

        /// <summary>
        /// 处理可能的测试连接消息
        /// </summary>
        private async Task HandlePossibleTestConnection()
        {
            try
            {
                // 设置读取超时
                _networkStream.ReadTimeout = 1000; // 1秒超时

                // 检查是否有测试消息
                var buffer = new byte[1024];
                int bytesRead = await _networkStream.ReadAsync(buffer, 0, buffer.Length);

                if (bytesRead > 0)
                {
                    var message = Encoding.UTF8.GetString(buffer, 0, bytesRead);

                    if (message == "TEST_CONNECTION")
                    {
                        Console.WriteLine("收到测试连接消息，发送响应...");

                        // 发送响应
                        var response = Encoding.UTF8.GetBytes("TEST_RESPONSE");
                        await _networkStream.WriteAsync(response, 0, response.Length);

                        // 关闭当前连接，等待实际的文件传输连接
                        CloseConnections();
                        Console.WriteLine("测试完成，等待实际文件传输...");

                        // 重新等待发送端连接
                        StartListening();
                        _client = await _listener.AcceptTcpClientAsync();
                        _networkStream = _client.GetStream();
                    }
                    else
                    {
                        // 不是测试消息，可能是文件信息，保存到预读取数据中
                        Console.WriteLine("收到文件数据，开始处理...");
                        _preReadData.Write(buffer, 0, bytesRead);
                        _preReadData.Position = 0; // 重置位置以便读取
                    }
                }
            }
            catch (IOException)
            {
                // 读取超时，没有测试消息，继续正常流程
                Console.WriteLine("没有测试消息，继续正常传输流程");
            }
        }

        /// <summary>
        /// 从网络流或预读取数据中读取数据
        /// </summary>
        private async Task<int> ReadFromStream(byte[] buffer, int offset, int count)
        {
            if (_preReadData.Length > 0 && _preReadData.Position < _preReadData.Length)
            {
                // 从预读取数据中读取
                int bytesRead = await _preReadData.ReadAsync(buffer, offset, count);
                if (bytesRead < count)
                {
                    // 预读取数据不够，从网络流中读取剩余部分
                    int remaining = count - bytesRead;
                    int additionalBytes = await _networkStream.ReadAsync(buffer, offset + bytesRead, remaining);
                    return bytesRead + additionalBytes;
                }
                return bytesRead;
            }
            else
            {
                // 直接从网络流中读取
                return await _networkStream.ReadAsync(buffer, offset, count);
            }
        }

        /// <summary>
        /// 等待取消输入
        /// </summary>
        private async Task<bool> WaitForCancelInput()
        {
            while (_isTransferring && _isReceivingFileInfo)
            {
                if (Console.KeyAvailable)
                {
                    var key = Console.ReadKey(true);
                    if (key.KeyChar == '0')
                    {
                        return true;
                    }
                }
                await Task.Delay(100);
            }
            return false;
        }

        /// <summary>
        /// 连接到接收端
        /// </summary>
        private async Task ConnectToReceiver()
        {
            _client = new TcpClient();
            await _client.ConnectAsync(_transferInfo.IpAddress, _transferInfo.Port);
            _networkStream = _client.GetStream();
        }

        /// <summary>
        /// 启动监听
        /// </summary>
        private void StartListening()
        {
            _listener = new TcpListener(System.Net.IPAddress.Any, _transferInfo.Port);
            _listener.Start();
        }

        /// <summary>
        /// 等待发送端连接
        /// </summary>
        private async Task WaitForSender()
        {
            _client = await _listener.AcceptTcpClientAsync();
            _networkStream = _client.GetStream();
        }

        /// <summary>
        /// 发送文件信息
        /// </summary>
        private async Task SendFileInfo()
        {
            var fileInfo = new
            {
                FileName = _transferInfo.FileName,
                FileSize = _transferInfo.FileSize
            };

            var json = JsonSerializer.Serialize(fileInfo);
            var data = Encoding.UTF8.GetBytes(json);

            // 发送信息长度
            var lengthBytes = BitConverter.GetBytes(data.Length);
            await _networkStream.WriteAsync(lengthBytes, 0, lengthBytes.Length);

            // 发送信息内容
            await _networkStream.WriteAsync(data, 0, data.Length);
        }

        /// <summary>
        /// 接收文件信息
        /// </summary>
        private async Task ReceiveFileInfo()
        {
            try
            {
                // 设置读取超时
                _networkStream.ReadTimeout = 5000; // 5秒超时

                // 读取信息长度
                var lengthBytes = new byte[4];
                int bytesRead = 0;
                while (bytesRead < lengthBytes.Length)
                {
                    int read = await ReadFromStream(lengthBytes, bytesRead, lengthBytes.Length - bytesRead);
                    if (read == 0)
                    {
                        // 连接正常关闭，不是错误
                        Console.WriteLine("连接已关闭，等待重新连接...");
                        return;
                    }
                    bytesRead += read;
                }
                var length = BitConverter.ToInt32(lengthBytes, 0);

                // 读取信息内容
                var data = new byte[length];
                bytesRead = 0;
                while (bytesRead < data.Length)
                {
                    int read = await ReadFromStream(data, bytesRead, data.Length - bytesRead);
                    if (read == 0)
                    {
                        // 连接正常关闭，不是错误
                        Console.WriteLine("连接已关闭，等待重新连接...");
                        return;
                    }
                    bytesRead += read;
                }

                var json = Encoding.UTF8.GetString(data);

                // 检查JSON是否有效
                if (string.IsNullOrWhiteSpace(json) || !json.Trim().StartsWith("{"))
                {
                    throw new Exception("接收到的数据不是有效的JSON格式");
                }

                var fileInfo = JsonSerializer.Deserialize<JsonElement>(json);

                // 更新传输信息
                _transferInfo.FileName = fileInfo.GetProperty("FileName").GetString();
                _transferInfo.FileSize = fileInfo.GetProperty("FileSize").GetInt64();

                // 设置保存路径
                _transferInfo.FilePath = Path.Combine(_transferInfo.SaveDirectory, _transferInfo.FileName);
            }
            catch (IOException ioEx) when (ioEx.InnerException is SocketException socketEx &&
                                          (socketEx.SocketErrorCode == SocketError.TimedOut ||
                                           socketEx.SocketErrorCode == SocketError.ConnectionReset))
            {
                // 网络超时或连接重置，不是严重错误
                Console.WriteLine("网络连接超时或重置，等待重新连接...");
                throw new Exception("网络连接问题，请检查网络状态");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"接收文件信息失败: {ex.Message}");
                throw;
            }
        }

        /// <summary>
        /// 发送文件数据
        /// </summary>
        private async Task SendFileData()
        {
            const int bufferSize = 81920; // 80KB
            var buffer = new byte[bufferSize];
            long totalBytesRead = 0;

            using (var fileStream = new FileStream(_transferInfo.FilePath, FileMode.Open, FileAccess.Read))
            {
                if (_transferInfo.TransferredBytes > 0)
                {
                    fileStream.Seek(_transferInfo.TransferredBytes, SeekOrigin.Begin);
                }

                int bytesRead;
                while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length, _cancellationTokenSource.Token)) > 0)
                {
                    if (_cancellationTokenSource.Token.IsCancellationRequested)
                    {
                        break;
                    }

                    await _networkStream.WriteAsync(buffer, 0, bytesRead, _cancellationTokenSource.Token);
                    totalBytesRead += bytesRead;
                    _transferInfo.TransferredBytes = totalBytesRead;

                    // 保存传输状态
                    SaveTransferState();
                }
            }
        }

        /// <summary>
        /// 接收文件数据
        /// </summary>
        private async Task ReceiveFileData(bool isResume)
        {
            const int bufferSize = 81920; // 80KB
            var buffer = new byte[bufferSize];
            long totalBytesRead = 0;
            var mode = isResume ? FileMode.Append : FileMode.Create;

            // 确保文件路径有效
            if (string.IsNullOrEmpty(_transferInfo.FilePath))
            {
                throw new Exception("文件路径无效，无法接收文件数据");
            }

            using (var fileStream = new FileStream(_transferInfo.FilePath, mode, FileAccess.Write))
            {
                if (isResume)
                {
                    totalBytesRead = fileStream.Length;
                    _transferInfo.TransferredBytes = totalBytesRead;
                }

                int bytesRead;
                while ((bytesRead = await ReadFromStream(buffer, 0, buffer.Length)) > 0)
                {
                    if (_cancellationTokenSource.Token.IsCancellationRequested)
                    {
                        break;
                    }

                    await fileStream.WriteAsync(buffer, 0, bytesRead, _cancellationTokenSource.Token);
                    totalBytesRead += bytesRead;
                    _transferInfo.TransferredBytes = totalBytesRead;

                    // 保存传输状态
                    SaveTransferState();
                }
            }
        }

        /// <summary>
        /// 启动进度显示
        /// </summary>
        private void StartProgressDisplay()
        {
            _progressTimer = new System.Timers.Timer(1000);
            _progressTimer.Elapsed += (sender, e) =>
            {
                if (_isTransferring && !_isReceivingFileInfo)
                {
                    double progress = (_transferInfo.FileSize > 0)
                        ? (double)_transferInfo.TransferredBytes / _transferInfo.FileSize * 100
                        : 0;

                    Console.WriteLine($"传输进度: {progress:F2}% ({_transferInfo.TransferredBytes} / {_transferInfo.FileSize} 字节)");
                }
            };
            _progressTimer.Start();
        }

        /// <summary>
        /// 停止进度显示
        /// </summary>
        private void StopProgressDisplay()
        {
            _progressTimer?.Stop();
            _progressTimer?.Dispose();
        }

        /// <summary>
        /// 保存传输状态
        /// </summary>
        private void SaveTransferState()
        {
            try
            {
                var json = JsonSerializer.Serialize(_transferInfo, new JsonSerializerOptions { WriteIndented = true });
                File.WriteAllText(_transferInfo.TempFilePath, json);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"保存传输状态失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 清理临时文件
        /// </summary>
        private void CleanupTempFiles()
        {
            try
            {
                if (File.Exists(_transferInfo.TempFilePath))
                {
                    File.Delete(_transferInfo.TempFilePath);
                }
                _preReadData?.Dispose();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"清理临时文件失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 关闭连接
        /// </summary>
        private void CloseConnections()
        {
            _networkStream?.Close();
            _client?.Close();
            _listener?.Stop();
            _fileStream?.Close();
            _preReadData?.Dispose();
            _preReadData = new MemoryStream();
        }

        /// <summary>
        /// 取消传输
        /// </summary>
        public void CancelTransfer()
        {
            _cancellationTokenSource.Cancel();
        }
    }
}